home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 9 / CDACTUAL9.iso / share / Dos / VARIOS / pascal / SWAG9605.DDD / 0076_Dynamic Arrays like VB.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-05-31  |  5.7 KB  |  218 lines

  1. {added by E.L. Lagerburg}
  2.  
  3.  
  4. Unit U_Array;
  5.  
  6. {Dynamic array by E.L. Lagerburg from the Netherlands}
  7.  
  8.  
  9. interface
  10.   Uses SysUtils;
  11.  
  12. const MaxArray = MaxInt div 8;
  13.  
  14. Type
  15.  
  16.   PByteArray=^TByteArray;
  17.   TByteArray=array[0..MaxArray] of byte ;
  18.  
  19.   TIndexEvent = Procedure(Sender:Tobject;Situation:Integer;Rec:Pointer;Index:Integer) of object;
  20.  
  21.  
  22.   Tarray = Class(TObject)
  23.   Private
  24.      FOnForIndex:TIndexEvent;
  25.      FOnForEach:TIndexEvent;
  26.      FArray:PByteArray;
  27.      FRecSize,
  28.      FRecCapacity:Integer;
  29.      FRecCount:Integer;
  30.   Protected
  31.      procedure SetCapacity(NewCapacity: Integer);
  32.      Function GetSize:Integer;
  33.      function Get(Index: Integer): Pointer;
  34.      procedure Put(Index: Integer; Rec: Pointer);
  35.      Procedure Error(Nr:Integer);
  36.      procedure Grow;
  37.      procedure SetCount(NewCount: Integer);
  38.    Public
  39.      Constructor Create(RecSize,RecCapacity:Integer);
  40.      Destructor Destroy; override;
  41.      function AddRecord(Rec:Pointer):Integer;
  42.      Procedure ForEach(Situation:Integer);
  43.      Procedure ForIndex(FromIndex,ToIndex,Situation:Integer);
  44.      procedure DeleteRecord(Index: Integer);
  45.      procedure MoveRecord(CurIndex, NewIndex: Integer);
  46.      procedure InsertRecord(Index: Integer;Rec:Pointer);
  47.      procedure ExchangeRecord(Index1, Index2: Integer);
  48.      Procedure Clear;
  49.      Property ByteArray:PByteArray read FArray;
  50.      Property Count:Integer read FRecCount write SetCount;
  51.      Property Size:Integer read GetSize;
  52.      Property RecordSize:Integer read FRecSize;
  53.      property Records[Index: Integer]: Pointer read Get write Put; default;
  54.      Property OnForEach:TIndexEvent read FOnForEach write FOnForEach;
  55.      Property OnForIndex:TIndexEvent read FOnForIndex write FOnForIndex;
  56.    end;
  57.  
  58.  
  59.    EArrayError = class(Exception);
  60.  
  61.  
  62. implementation
  63.  
  64. Constructor TArray.Create(RecSize,RecCapacity:Integer);
  65. Begin
  66.   Inherited Create;
  67.   FArray:=nil;
  68.   FRecSize:=RecSize;
  69.   FRecCapacity:=0;
  70.   FRecCount:=0;
  71.   SetCapacity(RecCapacity);
  72. end;
  73.  
  74. Procedure TArray.Error(Nr:Integer);
  75. Begin
  76.   raise EArrayError.Create('Array index out of bounds '+intToStr(Nr));
  77. End;
  78.  
  79. procedure TArray.SetCapacity(NewCapacity: Integer);
  80. Begin
  81.   if (NewCapacity < FRecCount) or (NewCapacity > MaxArray) then Error(1);
  82.   if NewCapacity <> FRecCapacity then
  83.   begin
  84.     ReallocMem(FArray, NewCapacity * FRecSize);
  85.     FRecCapacity := NewCapacity;
  86.   end;
  87. end;
  88.  
  89. Function TArray.AddRecord(Rec:Pointer):Integer;
  90. begin
  91.   Result := FRecCount;
  92.   if Result = FRecCapacity then Grow;
  93.   System.Move(Rec^,Farray^[FRecSize*FRecCount],FRecSize);
  94.   inc(FRecCount);
  95. end;
  96.  
  97. procedure TArray.InsertRecord(Index: Integer;Rec:Pointer);
  98. begin
  99.   if (Index < 0) or (Index > FRecCount) then Error(2);
  100.   if FRecCount = FRecCapacity then Grow;
  101.   if Index < FRecCount then
  102.     System.Move(FArray^[FRecSize*Index],FArray^[FRecSize*Index+1],
  103.       (FRecCount - Index) * FRecSize);
  104.   System.Move(Rec^,Farray^[FRecSize*Index],FRecSize);
  105.   Inc(FRecCount);
  106. end;
  107.  
  108. procedure TArray.DeleteRecord(Index: Integer);
  109. begin
  110.   if (Index < 0) or (Index >= FRecCount) then Error(3);
  111.   Dec(FRecCount);
  112.   if Index < FRecCount then
  113.     System.Move(FArray^[FRecSize*(Index + 1)],FArray^[FRecSize*Index],
  114.       (FRecCount - Index) * FRecSize);
  115. end;
  116.  
  117. procedure TArray.MoveRecord(CurIndex, NewIndex: Integer);
  118. var
  119.   Rec:PByteArray;
  120. begin
  121.   if CurIndex <> NewIndex then
  122.   begin
  123.     if (NewIndex < 0) or (NewIndex >= FRecCount) then Error(4);
  124.     Rec:=nil;
  125.     ReallocMem(Rec,FRecSize);
  126.     System.Move(Farray^[FRecSize*CurIndex],Rec^,FRecSize);
  127.     DeleteRecord(CurIndex);
  128.     InsertRecord(NewIndex,Rec);
  129.     ReallocMem(Rec,0);
  130.   end;
  131. end;
  132.  
  133. procedure TArray.ExchangeRecord(Index1, Index2: Integer);
  134. var
  135.   Rec:PByteArray;
  136. begin
  137.   if (Index1 < 0) or (Index1 >= FRecCount) or
  138.     (Index2 < 0) or (Index2 >= FRecCount) then Error(5);
  139.   Rec:=nil;
  140.   ReallocMem(Rec,FRecSize);
  141.   System.Move(Farray^[FRecSize*Index1],Rec^,FRecSize);
  142.   System.Move(Farray^[FRecSize*Index2],Farray^[FRecSize*Index1],FRecSize);
  143.   System.Move(Rec^,Farray^[FRecSize*Index2],FRecSize);
  144.   ReallocMem(Rec,0);
  145. end;
  146.  
  147. procedure TArray.SetCount(NewCount: Integer);
  148. begin
  149.   if (NewCount < 0) or (NewCount > MaxArray) then Error(6);
  150.   if NewCount > FRecCapacity then SetCapacity(NewCount);
  151.   if NewCount > FRecCount then
  152.     FillChar(FArray^[FRecCount*FRecSize],(NewCount - FRecCount) * FRecSize, 0);
  153.   FRecCount := NewCount;
  154. end;
  155.  
  156. procedure TArray.Grow;
  157. var
  158.   Delta: Integer;
  159. begin
  160.   if FRecCapacity > 8 then Delta := 16 else
  161.     if FRecCapacity > 4 then Delta := 8 else
  162.       Delta := 4;
  163.   SetCapacity(FRecCapacity + Delta);
  164. end;
  165.  
  166. Function TArray.Get(Index: Integer): Pointer;
  167. Begin
  168.   if (Index < 0) or (Index >= FRecCount) then Error(7);
  169.   Result:=@Farray^[FRecSize*Index];
  170. End;
  171.  
  172. procedure TArray.Clear;
  173. begin
  174.   FRecCount:=0;
  175.   SetCapacity(0);
  176. end;
  177.  
  178. Procedure TArray.Put(Index: Integer; Rec: Pointer);
  179. Begin
  180.   if (Index < 0) or (Index >= FRecCount) then Error(8);
  181.   System.Move(Rec^,Farray^[FRecSize*Index],FRecSize);
  182. End;
  183.  
  184. Procedure TArray.ForEach(Situation:Integer);
  185. Var Teller:Integer;
  186. Begin
  187.   If not Assigned(FOnForEach) then exit;
  188.   For Teller:=0 to FRecCount-1 do
  189.   Begin
  190.     FOnForEach(Self,Situation,Get(Teller),Teller);
  191.   End;
  192. End;
  193.  
  194. Procedure TArray.ForIndex(FromIndex,ToIndex,Situation:Integer);
  195. Var Teller:Integer;
  196. Begin
  197.   If not Assigned(FOnForIndex) then exit;
  198.   if (FromIndex < 0) or (FromIndex >= FRecCount) then Error(9);
  199.   if (ToIndex < 0) or (ToIndex >= FRecCount) then Error(10);
  200.   For Teller:=FromIndex to ToIndex do
  201.   Begin
  202.     FOnForIndex(Self,Situation,Get(Teller),Teller);
  203.   End;
  204. End;
  205.  
  206. Function TArray.GetSize:Integer;
  207. Begin
  208.   Result:=FRecSize * FRecCount;
  209. end;
  210.  
  211. Destructor TArray.Destroy;
  212. Begin
  213.   Clear;
  214.   Inherited Destroy;
  215. End;
  216.  
  217. end.
  218.